/* (PARI-GP) R. J. Cano, Jul 19 2014
 * 
 * Code generation routine. Purpose: 
 * 
 *  << To list and count all the n-ary combinations for the integers between "str1" and "str2" >>
 *
 * This routine generates another routine that performs the described task based upon a pretty simple "summation-only"
 * algorithm inspired by the study of the Newtown's 2nd Law obtaining it from the Lagrangian in Classical Mechanics,
 * due the omnipresence of The Combinatorics there in the underlying Tensor Algebra and Calculus required for all
 * kind of proofs.
 * 
 *  Notes: After a copy-and-paste operation made with the output of gen00(),
 *         and the execution of such generated routine for some particular case(s),
 * 
 *  #1) The list printing is optional!.
 * 
 *  #2) Verification(s):
 * 
 *        The answer value must be: binomial("str2"-"str1"+1, n) or Zero;
 * 
 *        Non-zero if and only if "str2"-"str1"+1 >= n, or when it makes sense to talk about n-ary combinations.
 * 
 *  #3) Notice that negative values are allowed.
 * 
*/ 
gen00=(n,str1="x",str2="y")->{print1("combine_"n"=("str1","str2",prnLst=1)->{my(q=0);for(x0="str1","str2",");for(k=1,n-1,print1("for(x"k"="str1",x"1*(k-1)"-1,"));/**/print1("q++;if(prnLst,print([x"1*(n-1)""if(n>1,",","]"));forstep(k=n-1,1,-1,print1("x"k-1,if(k==1,"]",",")));print1("))");/**/for(k=1,n,print1(")"));print1(";q}\n")}

/* Sample output / Examples: Assuming that we are in the middle of a GP Calculator worksession (Version >= 2.7.1);

----------------------------------------------------------------------------------------------------------------------
? gen00(3)
combine_3=(x,y,prnLst=1)->{my(q=0);for(x0=x,y,for(x1=x,x0-1,for(x2=x,x1-1,q++;if(prnLst,print([x2,x1,x0])))));q}
time = 1 ms. 
?
----------------------------------------------------------------------------------------------------------------------

  We copy and paste the previous answer. Yes, such source code generated by the call to gen00() passing 3 as argument:

----------------------------------------------------------------------------------------------------------------------
? combine_3=(x,y,prnLst=1)->{my(q=0);for(x0=x,y,for(x1=x,x0-1,for(x2=x,x1-1,q++;if(prnLst,print([x2,x1,x0])))));q}
%2 = (x,y,prnLst=1)->my(q=0);for(x0=x,y,for(x1=x,x0-1,for(x2=x,x1-1,q++;if(prnLst,print([x2,x1,x0])))));q
?
----------------------------------------------------------------------------------------------------------------------

  This is supposed to perform the count and list of ternary combinations of integer numbers.

  Now that it is ready to be used. Let us call it using for example: 1,0

----------------------------------------------------------------------------------------------------------------------
? combine_3(1,0)
%3 = 0
? 
----------------------------------------------------------------------------------------------------------------------

  Hmmm!... but nothing happened. That is because 0-1+1 < 3; Nothing bad, it falls inside the expected behavior.
  
  Now let's try with: -3, 3
  
----------------------------------------------------------------------------------------------------------------------
? combine_3(-3,3)
[-3, -2, -1]
[-3, -2, 0]
[-3, -1, 0]
[-2, -1, 0]
[-3, -2, 1]
[-3, -1, 1]
[-2, -1, 1]
[-3, 0, 1]
[-2, 0, 1]
[-1, 0, 1]
[-3, -2, 2]
[-3, -1, 2]
[-2, -1, 2]
[-3, 0, 2]
[-2, 0, 2]
[-1, 0, 2]
[-3, 1, 2]
[-2, 1, 2]
[-1, 1, 2]
[0, 1, 2]
[-3, -2, 3]
[-3, -1, 3]
[-2, -1, 3]
[-3, 0, 3]
[-2, 0, 3]
[-1, 0, 3]
[-3, 1, 3]
[-2, 1, 3]
[-1, 1, 3]
[0, 1, 3]
[-3, 2, 3]
[-2, 2, 3]
[-1, 2, 3]
[0, 2, 3]
[1, 2, 3]
time = 1 ms.
%4 = 35
?
----------------------------------------------------------------------------------------------------------------------

  ...35?; Yes!, 35. What it did mean is: binomial(3-(-3)+1,3) == binomial(7,3) or 35;
  
  Ok, but wait!... Aren't there repeated numbers?. ...Yep, but notice that -3 (or -1*3) is not the same than 3. Both
  might have the same absolute value, but they are treated by the algorithm like what indeed they are: Different numbers.
  
----------------------------------------------------------------------------------------------------------------------

  Again, this time: 0,3,0

----------------------------------------------------------------------------------------------------------------------
? combine_3(0,3,0)
%5 = 4
?
----------------------------------------------------------------------------------------------------------------------

 4?... Straightforward as: 3-0+1 is 4, and binomial(4,3) is 4;
 
 Once more, now: 0,3,1 
 
----------------------------------------------------------------------------------------------------------------------
? combine_3(0,3,1)
[0, 1, 2]
[0, 1, 3]
[0, 2, 3]
[1, 2, 3]
%6 = 4
? 
----------------------------------------------------------------------------------------------------------------------
 
 Finally a last example, in some sense equivalent to 0,3,1; This is: 1,4,1
 
----------------------------------------------------------------------------------------------------------------------
? combine_3(1,4,1)
[1, 2, 3]
[1, 2, 4]
[1, 3, 4]
[2, 3, 4]
%7 = 4
----------------------------------------------------------------------------------------------------------------------

  The equivalence mentioned there is the fact that viewed as matrices the output for 1,4,1 is the same output
  for 0,3,1 after adding 1 to each one of the numbers composing it.
   
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The End ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  Isn't it funny?:
  Just 3 lines of code against 48 times such length in illustrations/documentation (3.5 pages @ 1024*768 of screen resolution)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/